from datetime import datetime

from inc.models import db, JiraProject, JiraTask, JiraReview, JiraReviewNode, JiraStage
from inc import logger

class ProjectWorkflow:
    """项目状态流转服务"""

    @staticmethod
    def submit_for_review(project_id, user_id):
        """提交项目审核"""
        project = JiraProject.query.get_or_404(project_id)

        # 检查权限
        if project.owner_id != user_id:
            raise PermissionError("只有项目负责人可以提交审核")

        # 状态检查
        if project.status != JiraProject.DRAFT:
            raise ValueError("只有草稿状态的项目可以提交审核")

        # 更新状态
        project.status = JiraProject.PENDING
        project.submitted_at = datetime.now()

        # 获取默认审核节点
        default_node = JiraReviewNode.query.filter_by(description='默认审核节点').first()
        if not default_node:
            default_node = JiraReviewNode(description='默认审核节点')
            db.session.add(default_node)
            db.session.commit()

        # 创建审批记录
        approval = JiraReview(
            project_id=project_id,
            submitter_id=user_id,
            reviewer_id=project.first_approver_id,  # 使用项目的第一审批人
            node_id=default_node.id,  # 设置默认审核节点
            status='pending',
            notes='项目提交审核',
            created_at=datetime.now()
        )
        db.session.add(approval)
        db.session.commit()
        return project

    @staticmethod
    def approve_project(project_id, reviewer_id, notes=""):
        """批准项目"""
        project = JiraProject.query.get_or_404(project_id)

        # 状态检查
        if project.status != JiraProject.PENDING:
            raise ValueError("只有待审核状态的项目可以批准")

        # 更新状态
        project.status = JiraProject.CLOSED
        project.reviewed_at = datetime.now()
        project.reviewer_id = reviewer_id
        project.review_notes = notes

        db.session.commit()
        return project

    @staticmethod
    def start_project(project_id, user_id):
        """开始项目"""
        project = JiraProject.query.get_or_404(project_id)

        # 检查权限
        if project.owner_id != user_id:
            raise PermissionError("只有项目负责人可以开始项目")

        # 状态检查
        if project.status != JiraProject.APPROVED:
            raise ValueError("只有已批准的项目可以开始")

        project.status = JiraProject.IN_PROGRESS
        project.started_at = datetime.now()
        db.session.commit()
        return project

    @staticmethod
    def request_project_closure(project_id, user_id):
        """请求项目结项"""
        project = JiraProject.query.get_or_404(project_id)

        # 检查权限
        if project.owner_id != user_id:
            raise PermissionError("只有项目负责人可以请求结项")

        # 状态检查
        if project.status not in [JiraProject.COMPLETED, JiraProject.IN_PROGRESS]:
            raise ValueError("只有进行中或已完成的项目可以请求结项")

        # 检查未完成任务
        incomplete_tasks = JiraTask.query.join(
            JiraStage, JiraTask.stage_id == JiraStage.id
        ).filter(
            JiraStage.project_id == project_id,
            JiraTask.status != JiraTask.COMPLETED
        ).count()

        if incomplete_tasks > 0:
            raise ValueError(f"当前项目中还有{incomplete_tasks}个任务未完成，请先完成任务")

        # 获取默认审核节点
        default_node = JiraReviewNode.query.filter_by(
            description='结项审核节点'
        ).first()
        if not default_node:
            default_node = JiraReviewNode(description='结项审核节点')
            db.session.add(default_node)
            db.session.commit()

        # 更新状态为结项审核中
        project.status = JiraProject.CLOSING
        project.closure_requested_at = datetime.now()
        db.session.commit()

        # 检查是否已存在未处理的结项审批
        existing_review = JiraReview.query.filter_by(
            project_id=project_id,
            is_closure_review=True,
            status='pending'
        ).first()

        if not existing_review:
            # 创建结项审批记录
            closure_review = JiraReview(
                project_id=project_id,
                submitter_id=user_id,
                reviewer_id=project.first_approver_id,
                node_id=default_node.id,
                status='pending',
                is_closure_review=True,
                notes='项目结项审批',
                created_at=datetime.now()
            )
            db.session.add(closure_review)
            db.session.commit()
        else:
            # 更新现有审批记录
            existing_review.submitter_id = user_id
            existing_review.notes = '项目结项审批（重新提交）'
            existing_review.created_at = datetime.now()
            db.session.commit()
        return project

    @staticmethod
    def approve_project_closure(project_id, reviewer_id, notes="", score=0):
        """批准项目结项"""
        project = JiraProject.query.get_or_404(project_id)

        # 检查权限
        if project.first_approver_id != reviewer_id:
            raise PermissionError("只有第一审批人可以批准结项")

        # 状态检查
        if project.status == JiraProject.CLOSED:
            raise ValueError("项目已经结项，不能重复审批")
        if project.status != JiraProject.CLOSING:
            raise ValueError("只有结项审核中的项目可以批准")

        # 检查是否已有批准的结项审批记录
        approved_closure = JiraReview.query.filter_by(
            project_id=project_id,
            is_closure_review=True,
            status='CLOSED'
        ).first()
        if approved_closure:
            raise ValueError("项目结项审批已经完成，不能重复审批")

        # 更新状态
        project.status = JiraProject.CLOSED
        project.closure_reviewed_at = datetime.now()
        project.closed_at = datetime.now()
        project.closure_score = score
        project.closure_notes = notes

        # 更新审批记录
        closure_review = JiraReview.query.filter_by(
            project_id=project_id,
            is_closure_review=True,
            status='pending'
        ).first()
        if closure_review:
            closure_review.status = 'approved'
            closure_review.reviewed_at = datetime.now()
            closure_review.review_notes = notes
            db.session.add(closure_review)  # 显式添加对象到session

        # 确保所有变更一次性提交
        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            logger.error(f"批准结项时数据库提交失败: {str(e)}")
            raise ValueError("批准结项失败，请重试")
        return project

    @staticmethod
    def reject_project_closure(project_id, reviewer_id, notes=""):
        """拒绝项目结项"""
        project = JiraProject.query.get_or_404(project_id)

        # 检查权限
        if project.first_approver_id != reviewer_id:
            raise PermissionError("只有第一审批人可以拒绝结项")

        # 状态检查
        if project.status != JiraProject.CLOSING:
            raise ValueError("只有结项审核中的项目可以拒绝")

        # 更新状态
        project.status = JiraProject.IN_PROGRESS
        project.closure_rejected_at = datetime.now()
        project.closure_notes = notes

        # 更新审批记录
        closure_review = JiraReview.query.filter_by(
            project_id=project_id,
            is_closure_review=True,
            status='in_progress'
        ).first()
        if closure_review:
            closure_review.status = 'in_progress'
            closure_review.reviewed_at = datetime.now()
            closure_review.review_notes = notes
            db.session.commit()

        db.session.commit()
        return project

    @staticmethod
    def complete_project(project_id, user_id):
        """完成项目"""
        project = JiraProject.query.get_or_404(project_id)

        # 检查权限
        if project.owner_id != user_id:
            raise PermissionError("只有项目负责人可以完成项目")

        # 检查所有任务是否已完成
        incomplete_tasks = JiraTask.query.filter_by(
            stage_id=JiraStage.query.filter_by(project_id=project_id).subquery(),
            status=JiraTask.COMPLETED
        ).count()

        if incomplete_tasks > 0:
            raise ValueError(f"项目还有{incomplete_tasks}个任务未完成，请先完成所有任务")

        # 更新项目状态
        project.status = JiraProject.COMPLETED
        project.completed_at = datetime.now()
        db.session.commit()
        return project

class TaskWorkflow:
    """任务状态流转服务"""

    @staticmethod
    def assign_task(task_id, assigner_id, assignee_id):
        """分配任务"""
        task = JiraTask.query.get_or_404(task_id)
        project = task.stage.project

        # 检查权限
        if not any(m.member_id == assigner_id for m in project.members):
            raise PermissionError("无权分配此任务")

        task.assignee_id = assignee_id
        task.status = JiraTask.IN_PROGRESS
        db.session.commit()
        return task

    @staticmethod
    def complete_task(task_id, user_id):
        """完成任务"""
        task = JiraTask.query.get_or_404(task_id)

        # 检查权限
        if task.assignee_id != user_id:
            raise PermissionError("只有任务负责人可以完成任务")

        task.status = JiraTask.COMPLETED
        task.completed_at = datetime.now()
        db.session.commit()

        # 更新项目进度
        if task.stage and task.stage.project:
            task.stage.project.update_progress()
            db.session.commit()

        return task